webappApp
  .factory('geocoder', function() {
    return new google.maps.Geocoder();
  })
  .factory('addresses', ['geocoder', '$q', function(geocoder, $q) {
    return {
      getAddress: function (location, scope) {
        var address = $q.defer(), self = this;
        geocoder.geocode({
          location: new google.maps.LatLng(
            location.latitude,
            location.longitude
          )
        }, function(results, status) {
          scope.$apply(function () {
            if (status == google.maps.GeocoderStatus.OK) {
                address.resolve(self.parseAddress(results[0]));
            } else {
              address.reject(status);
            }
          });
        }, function (e) {
          scope.$apply(function () {
            address.reject(e);
          });
        });
        return address.promise;
      },

      parseAddress: function (address) {
        var created = {}, streetNum;
        angular.forEach(address.address_components, function (component) {
            angular.forEach(component.types, function (type) {
              if (angular.equals('street_number', type)) {
                streetNum = component.short_name;
              }
              if (['street_address', 'intersection', 'route','premise','subpremise','park'].indexOf(type) != -1) {
                created.address = component.short_name;
              }
              if (['locality'].indexOf(type) != -1) {
                created.city = component.short_name;
              }
              if (['administrative_area_level_1'].indexOf(type) != -1) {
                created.state = component.short_name;
              }
              if (['country'].indexOf(type) != -1) {
                created.country = component.short_name;
              }
              if (['postal_code'].indexOf(type) != -1) {
                created.zipcode = component.short_name;
              }
            });
          });
          if (created.address || created.city || created.state || created.country || created.zipcode) {
            created.address = streetNum + ' ' + created.address;
            return created;
          }
      }
    };
  }]);